package com.base.data.tools;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
//import android.database.sqlite.SQLiteDatabase;
import net.sqlcipher.database.SQLiteDatabase;

import android.text.TextUtils;

import androidx.annotation.NonNull;

import com.base.common.app.BaseConstant;
import com.base.common.model.bean.KeyValue;
import com.base.common.utils.DateUtils;
import com.base.common.utils.JavaMethod;
import com.base.common.utils.UIUtils;
import com.base.data.annotations.TableField;
import com.base.data.annotations.TableId;
import com.base.data.annotations.TableName;
import com.orm.SugarContext;
import com.orm.SugarDb;
import com.orm.SugarRecord;
import com.orm.helper.ManifestHelper;
import com.orm.helper.NamingHelper;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * PRAGMA table_info(t_sys_role)
 */

public class SqliteUtils {

    /**
     * ----------------------------------------------------------------------------------------------------------------------------------------------------------
     * 1，将assets里面的数据库迁移到默认的dataBase目录里面
     * 2,初始化 SugarORM  用于操作数据库
     */
    public static void initDataBase(Context context) {
//        DatabaseUtil.packDataBase(context, "dataBase/gauge.db");
    }


    public static int delete(@NonNull Class<?> type, @NonNull String idFieldName, @NonNull String idValue) {
        if (TextUtils.isEmpty(idFieldName) || TextUtils.isEmpty(idValue)) return 0;
        SQLiteDatabase database = SugarRecord.getSugarDataBase();
        return database.delete(toTabNameDefault(type), idFieldName + " =?", new String[]{idValue});
    }

    public static long insert(String tabName, ContentValues values) {
        SQLiteDatabase database = SugarRecord.getSugarDataBase();
        return database.insertWithOnConflict(tabName, null, values, SQLiteDatabase.CONFLICT_REPLACE);
    }

    /**
     * 根据id更新数据
     *
     * @param type
     * @param values
     * @param idFieldName
     * @param idValue
     * @return
     */
    public static int updateId(Class<?> type, ContentValues values, String idFieldName, String idValue) {
        if (TextUtils.isEmpty(idFieldName) || TextUtils.isEmpty(idValue)) return -1;
        return update(toTabNameDefault(type), values, idFieldName + " =?", new String[]{idValue});
    }

    public static int update(String tabName, ContentValues values, String key, String keyValues) {
        return update(tabName, values, key + " =?", new String[]{keyValues});
    }

    /**
     * 更新数据
     */
    public static int update(String tabName, ContentValues values, String whereClause, String[] whereArgs) {
        SQLiteDatabase database = SugarRecord.getSugarDataBase();
        return database.update(tabName, values, whereClause, whereArgs);
    }

    public static void update(@NonNull String sql) {
        SQLiteDatabase database = SugarRecord.getSugarDataBase();
        database.execSQL(sql);
    }

    public static void update(@NonNull String sql, Object[] selectionArgs) {
        if (selectionArgs != null && selectionArgs.length > 0) {
            sql = String.format(sql, selectionArgs);
        }
        update(sql);
    }


    /**
     * 请求查询数据
     *
     * @param sql
     * @param selectionArgs
     */
    public static <T> List<T> find(Class<T> type, String sql, Object[] selectionArgs) {
        if (selectionArgs != null && selectionArgs.length > 0) {
            sql = String.format(sql, selectionArgs);
        }
        Cursor cursor = getSugarDb().getReadableDatabase().rawQuery(sql, null);
        return getEntitiesFromCursor(cursor, type);
    }

    /**
     * 请求查询数据
     *
     * @param sql
     */
    public static <T> List<T> rawQuery(@NonNull Class<T> type, @NonNull String sql) {
        Cursor cursor = getSugarDb().getReadableDatabase().rawQuery(sql, null);
        return getEntitiesFromCursor(cursor, type);
    }

    /**
     * @param cls
     * @param where 是否含有条件    where is_del=1       表示没有删除的字段
     * @return
     */
    public static int selectAllCount(@NonNull Class<?> cls, String... where) {
        String where_str = " ";
        where_str += where.length == 0 ? "" : where[0];

        String sql = "select count (*) from " + SqliteUtils.toTabNameDefault(cls) + where_str;
        Cursor cursor = getSugarDb().getReadableDatabase().rawQuery(sql, null);
        try {
            cursor.moveToFirst();
            int count = cursor.getInt(0);
            cursor.close();
            return count;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            cursor.close();
        }
        return 0;
    }


    public static <T> List<T> getEntitiesFromCursor(Cursor cursor, Class<T> type) {
        T entity = null;
        List<T> result = new ArrayList<>();
        try {
            while (cursor.moveToNext()) {
                //如是基本类型或基本类型的封装类型
                if (JavaMethod.isPrimitiveOrObject(type)) {
                    int count = cursor.getColumnCount();
                    if (count > 0) {
                        entity = JavaMethod.transformClass(cursor.getString(0), type);
                    }
                } else {
                    entity = type.getDeclaredConstructor().newInstance();
                    inflate(cursor, entity);
                }
                if (entity != null)
                    result.add(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            cursor.close();
        }

        return result;
    }

    /**
     * @param cursor
     * @param object
     */
    private static void inflate(Cursor cursor, @NonNull Object object) {

        if (object instanceof KeyValue) {
            int count = cursor.getColumnCount();
            if (count == 3) {
                KeyValue keyValue = (KeyValue) object;
                keyValue.setKey(cursor.getString(0));
                keyValue.setValue(cursor.getString(1));
                keyValue.setDesc(cursor.getString(2));
            }
        } else {
            Field[] fields = object.getClass().getDeclaredFields();
            for (Field field : fields) {

                if (field.isAnnotationPresent(TableField.class)) {
                    TableField tableField = field.getAnnotation(TableField.class);
                    if (!tableField.exist()) continue;
                }

                field.setAccessible(true);
                String colName = toSQLNameDefault(field);
                int columnIndex = cursor.getColumnIndex(colName);
                if (columnIndex < 0) continue;
                if (cursor.isNull(columnIndex)) {
                    continue;
                }

                try {
                    Object va = cursor.getString(columnIndex);
                    if (va == null) continue;
                    field.set(object, JavaMethod.transformClass(va, field.getType()));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }

            }
        }


    }

    public static String toSQLNameDefault(String camelCased) {

        return NamingHelper.toSQLNameDefault(camelCased);

        //小写
//        StringBuilder sb = new StringBuilder();
//        char[] buf = camelCased.toCharArray();
//
//        for (int i = 0; i < buf.length; i++) {
//            char prevChar = (i > 0) ? buf[i - 1] : 0;
//            char c = buf[i];
//            char nextChar = (i < buf.length - 1) ? buf[i + 1] : 0;
//            boolean isFirstChar = (i == 0);
//
//            if (isFirstChar || Character.isLowerCase(c) || Character.isDigit(c)) {
//                sb.append(Character.toUpperCase(c));
//            } else if (Character.isUpperCase(c)) {
//                if (Character.isLetterOrDigit(prevChar)) {
//                    if (Character.isLowerCase(prevChar)) {
//                        sb.append('_').append(c);
//                    } else if (nextChar > 0 && Character.isLowerCase(nextChar)) {
//                        sb.append('_').append(c);
//                    } else {
//                        sb.append(c);
//                    }
//                } else {
//                    sb.append(c);
//                }
//            } else {
//                sb.append(c);
//            }
//        }
//
//        return sb.toString().toLowerCase();
    }

    public static String toTabNameDefault(@NonNull Class<?> cls) {
        String tabName;
        if (cls.isAnnotationPresent(TableName.class)) {
            TableName tableName = cls.getAnnotation(TableName.class);
            tabName = tableName.value();
            if (TextUtils.isEmpty(tabName)) {
                tabName = toSQLNameDefault(cls.getSimpleName());
            }
        } else {
            tabName = toSQLNameDefault(cls.getSimpleName());
        }
        return tabName;
    }


    public static String toSQLNameDefault(@NonNull Field field) {
        String tabName;
        if (field.isAnnotationPresent(TableField.class)) {
            TableField tableName = field.getAnnotation(TableField.class);
            tabName = tableName.value();
            if (TextUtils.isEmpty(tabName)) {
                tabName = toSQLNameDefault(field.getName());
            }
        } else {
            tabName = toSQLNameDefault(field.getName());
        }
        return tabName;
    }

    public static <T> KeyValue<String, String, String> getTabIdField(@NonNull T bean) {

        for (Field field : bean.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(TableId.class)) {
                field.setAccessible(true);
                try {
                    Object obj = field.get(bean);
                    if (obj != null) {
                        return new KeyValue<>(field.getName(), obj.toString(), "");
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

    public static String getTabIdFieldName(@NonNull Class<?> type) {
        for (Field field : type.getDeclaredFields()) {
            if (field.isAnnotationPresent(TableId.class)) {
                return field.getName();
            }
        }
        return null;
    }

    public static String getTabIdName(@NonNull Class<?> type) {
        for (Field field : type.getDeclaredFields()) {
            if (field.isAnnotationPresent(TableId.class)) {
                return toSQLNameDefault(field);
            }
        }
        return null;
    }


    /**
     * 获SugarDb
     *
     * @return
     */

    public static SugarDb getSugarDb() {
        return SugarContext.getSugarContext().getSugarDb();
    }

    /**
     * 断开数据库链接
     *
     * @return
     */
    public static void close() {
        SugarContext.terminate();
    }

    /**
     * 立即备份
     */
    public static void backup_immediately(Context mContext) {
        String name = DateUtils.dateLongToString(0, "yyyy-MM-dd") + "_" + ManifestHelper.getDatabaseName();
        String err = DatabaseUtil.backUpDB(mContext, BaseConstant.backupSaveDir + "/" + name);
        if (err.equals("")) {
            UIUtils.showToastSafes("数据库备份成功！");
        } else {
            UIUtils.showToastSafes("数据库备份失败！" + err);
        }
    }


    public static void restoreDB(Context mContext, String backupDBPath) {

        close();
        String err = DatabaseUtil.restoreDB(mContext, backupDBPath);
        if (err.equals("")) {
            UIUtils.showToastSafes("数据库还原成功！");
        } else {
            UIUtils.showToastSafes("数据库还原失败！" + err);
        }
        SugarContext.init(mContext);
    }


}
